package org.breathe.dynamic.thread.pool.core.spring;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.breathe.dynamic.thread.pool.core.executor.ThreadPoolExecutorRegistry;
import org.breathe.dynamic.thread.pool.core.thread.BreatheDtpExecutor;
import org.breathe.thread.pool.common.anno.BreatheDtp;
import org.breathe.thread.pool.common.utils.ApplicationContextHolder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * 利用bean的生命周期来管理线程池
 * @author: breathe
 * @createTime: 2025-04-10
 */
@Slf4j
public class BreatheDtpPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (!(bean instanceof ThreadPoolExecutor)) {
            return bean;
        }

        if (bean instanceof BreatheDtpExecutor executor) {
            registerDynamic(executor);
            return executor;
        }

        BreatheDtp breatheDynamicThreadPool;
        try {
            breatheDynamicThreadPool = ApplicationContextHolder.findAnnotationOnBean(beanName, BreatheDtp.class);
            if (breatheDynamicThreadPool == null) {
                return bean;
            }
        } catch (NoSuchBeanDefinitionException ex) {
            log.error("this isn't bean with given name {}", beanName, ex);
            return bean;
        }
        String poolName = StrUtil.isNotBlank(breatheDynamicThreadPool.value()) ? breatheDynamicThreadPool.value() : beanName;
        registerCommon(poolName, (ThreadPoolExecutor) bean);
        return bean;
    }

    private void registerDynamic(BreatheDtpExecutor executor) {
        ThreadPoolExecutorRegistry.registerDynamic(executor, "beanPostProcessor");
    }

    private void registerCommon(String poolName,ThreadPoolExecutor executor) {
        ExecutorWrapper executorWrapper = new ExecutorWrapper();
        executorWrapper.setExecutor(executor);
        executorWrapper.setThreadPoolName(poolName);
        ThreadPoolExecutorRegistry.registerCommon(executorWrapper, poolName);
    }
}
